//
//	HOME AUTOMATION GATEWAY PROJECT
//
//  (c) 2008 mocom software GmbH & Co KG 
//	for European Microsoft Innovation Center
//
//  $Author: volker $
//  $Date: 2009-02-26 16:55:56 +0100 (Do, 26. Feb 2009) $
//  $Revision: 276 $
//
//  Microsoft dotNetMF Project
//  Copyright ©2001,2002,2003,2004 Microsoft Corporation
//  One Microsoft Way, Redmond, Washington 98052-6399 U.S.A.
//  All rights reserved.
//  MICROSOFT CONFIDENTIAL
//
//-----------------------------------------------------------------------------

#ifndef _AT91_SPI_H_1
#define _AT91_SPI_H_1 1

#define MAX_SPI_CHANNELS	AT91C_MAX_SPI

// -------- SPI_CR : (SPI Offset: 0x0) SPI Control Register --------
#define AT91C_SPI_SPIEN           (0x1 <<  0) // (SPI) SPI Enable
#define AT91C_SPI_SPIDIS          (0x1 <<  1) // (SPI) SPI Disable
#define AT91C_SPI_SWRST           (0x1 <<  7) // (SPI) SPI Software reset
#define AT91C_SPI_LASTXFER        (0x1 << 24) // (SPI) SPI Last Transfer

// -------- SPI_MR : (SPI Offset: 0x4) SPI Mode Register --------
#define AT91C_SPI_MSTR            (0x1 <<  0) // (SPI) Master/Slave Mode
#define AT91C_SPI_PS              (0x1 <<  1) // (SPI) Peripheral Select
#define AT91C_SPI_PS_FIXED        (0x0 <<  1) // (SPI) Fixed Peripheral Select
#define AT91C_SPI_PS_VARIABLE     (0x1 <<  1) // (SPI) Variable Peripheral Select
#define AT91C_SPI_PCSDEC          (0x1 <<  2) // (SPI) Chip Select Decode
#define AT91C_SPI_FDIV            (0x1 <<  3) // (SPI) Clock Selection
#define AT91C_SPI_MODFDIS         (0x1 <<  4) // (SPI) Mode Fault Detection
#define AT91C_SPI_LLB             (0x1 <<  7) // (SPI) Clock Selection
#define AT91C_SPI_PCS(x)          (((x)&0xf) << 16) // (SPI) Peripheral Chip Select
#define AT91C_SPI_DLYBCS(x)       (((x)&0xff) << 24) // (SPI) Delay Between Chip Selects

// -------- SPI_RDR : (SPI Offset: 0x8) Receive Data Register --------
#define AT91C_SPI_RD              (0xFFFF <<  0) // (SPI) Receive Data
#define AT91C_SPI_RPCS            (0xF << 16) // (SPI) Peripheral Chip Select Status

// -------- SPI_TDR : (SPI Offset: 0xc) Transmit Data Register --------
#define AT91C_SPI_TD              (0xFFFF <<  0) // (SPI) Transmit Data
#define AT91C_SPI_TPCS            (0xF << 16) // (SPI) Peripheral Chip Select Status

// -------- SPI_SR : (SPI Offset: 0x10) Status Register --------
#define AT91C_SPI_RDRF            (0x1 <<  0) // (SPI) Receive Data Register Full
#define AT91C_SPI_TDRE            (0x1 <<  1) // (SPI) Transmit Data Register Empty
#define AT91C_SPI_MODF            (0x1 <<  2) // (SPI) Mode Fault Error
#define AT91C_SPI_OVRES           (0x1 <<  3) // (SPI) Overrun Error Status
#define AT91C_SPI_ENDRX           (0x1 <<  4) // (SPI) End of Receiver Transfer
#define AT91C_SPI_ENDTX           (0x1 <<  5) // (SPI) End of Receiver Transfer
#define AT91C_SPI_RXBUFF          (0x1 <<  6) // (SPI) RXBUFF Interrupt
#define AT91C_SPI_TXBUFE          (0x1 <<  7) // (SPI) TXBUFE Interrupt
#define AT91C_SPI_NSSR            (0x1 <<  8) // (SPI) NSSR Interrupt
#define AT91C_SPI_TXEMPTY         (0x1 <<  9) // (SPI) TXEMPTY Interrupt
#define AT91C_SPI_SPIENS          (0x1 << 16) // (SPI) Enable Status

// -------- SPI_CSR : (SPI Offset: 0x30) Chip Select Register --------
#define AT91C_SPI_CPOL            (0x1 <<  0) 		// (SPI) Clock Polarity
#define AT91C_SPI_NCPHA           (0x1 <<  1) 		// (SPI) Clock Phase
#define AT91C_SPI_CSAAT           (0x1 <<  2) 		// (SPI) Chip Select Active After Transfer
#define AT91C_SPI_BITS_8          (0x0 <<  4) 		// (SPI) 8 Bits Per transfer
#define AT91C_SPI_BITS_9          (0x1 <<  4) 		// (SPI) 9 Bits Per transfer
#define AT91C_SPI_BITS_10         (0x2 <<  4)		// (SPI) 10 Bits Per transfer
#define AT91C_SPI_BITS_11         (0x3 <<  4)		// (SPI) 11 Bits Per transfer
#define AT91C_SPI_BITS_12         (0x4 <<  4)		// (SPI) 12 Bits Per transfer
#define AT91C_SPI_BITS_13         (0x5 <<  4)		// (SPI) 13 Bits Per transfer
#define AT91C_SPI_BITS_14         (0x6 <<  4)		// (SPI) 14 Bits Per transfer
#define AT91C_SPI_BITS_15         (0x7 <<  4)		// (SPI) 15 Bits Per transfer
#define AT91C_SPI_BITS_16         (0x8 <<  4)		// (SPI) 16 Bits Per transfer
#define AT91C_SPI_SCBR(x)         (((x)&0xff) <<  8) // (SPI) Serial Clock Baud Rate
#define AT91C_SPI_DLYBS(x)        (((x)&0xff) << 16) // (SPI) Serial Clock Baud Rate
#define AT91C_SPI_DLYBCT(x)       (((x)&0xff) << 24) // (SPI) Delay Between Consecutive Transfers

// -------- PDC_PTCR : (PDC Offset: 0x20) PDC Transfer Control Register --------
#define AT91C_PDC_RXTEN           (0x1 <<  0) // (PDC) Receiver Transfer Enable
#define AT91C_PDC_RXTDIS          (0x1 <<  1) // (PDC) Receiver Transfer Disable
#define AT91C_PDC_TXTEN           (0x1 <<  8) // (PDC) Transmitter Transfer Enable
#define AT91C_PDC_TXTDIS          (0x1 <<  9) // (PDC) Transmitter Transfer Disable

typedef volatile struct
{
	UINT32	CR;         // ( 0) Control Register
	UINT32	MR;      	// ( 4) Mode Register
	UINT32	RDR;     	// ( 8) Receive Data Register
	UINT32	TDR;     	// (12) Transmit Data Register
	UINT32	SR;      	// (16) Status Register
	UINT32	IER;     	// (20) Interrupt Enable Register
	UINT32	IDR;     	// (24) Interrupt Disable Register
	UINT32	IMR;     	// (28) Interrupt Mask Register
	UINT32	pad_a[4];	// (32,36,40,44)
	UINT32	CSR[4];    	// (48) Chip Select Register
	UINT32	pad_b[48];	// (64..252)
	void*	RPR;     	// (256) Receive Pointer Register
	UINT32	RCR;     	// (260) Receive Counter Register
	void*	TPR;     	// (264) Transmit Pointer Register
	UINT32	TCR;     	// (268) Transmit Counter Register
	void*	NRPR;    	// (272) Receive Next Pointer Register
	UINT32	NRCR;    	// (276) Receive Next Counter Register
	void*	NTPR;    	// (280) Transmit Next Pointer Register
	UINT32	NTCR;    	// (284) Transmit Next Counter Register
	UINT32	PTCR;    	// (288) PDC Transfer Control Register
	UINT32	PTSR;    	// (292) PDC Transfer Status Register
} AT91_SPI;


struct AT91_SPI_Driver
{
	BOOL m_Enabled[MAX_SPI_CHANNELS];
	
	static BOOL Initialize();
	static void Uninitialize();

    static void GetPins( UINT32 spi_mod, GPIO_PIN& msk, GPIO_PIN& miso, GPIO_PIN& mosi );

	static BOOL nWrite16_nRead16(const SPI_CONFIGURATION& Configuration, UINT16* Write16, INT32 WriteCount, UINT16* Read16, INT32 ReadCount, INT32 ReadStartOffset);
	static BOOL nWrite8_nRead8(const SPI_CONFIGURATION& Configuration, UINT8*  Write8 , INT32 WriteCount, UINT8*  Read8 , INT32 ReadCount, INT32 ReadStartOffset);

	static BOOL Xaction_Start(const SPI_CONFIGURATION& Configuration);
	static BOOL Xaction_Stop(const SPI_CONFIGURATION& Configuration);

	static BOOL Xaction_nWrite16_nRead16(SPI_XACTION_16& Transaction);
	static BOOL Xaction_nWrite8_nRead8(SPI_XACTION_8&  Transaction);

private:
	static void SPI0_Isr(void* Param);
	static void SPI1_Isr(void* Param);
};

//
// AT91_SPI_DRIVER
//////////////////////////////////////////////////////////////////////////////
#endif
